package com.seer.srd.qingdao

import com.mongodb.client.model.UpdateOptions
import com.seer.srd.BusinessError
import com.seer.srd.db.MongoDBManager
import com.seer.srd.domain.ChangeTrace
import com.seer.srd.eventbus.EventBus
import com.seer.srd.robottask.RobotTask
import com.seer.srd.storesite.StoreSite
import com.seer.srd.storesite.StoreSiteService
import org.bson.codecs.pojo.annotations.BsonId
import org.litote.kmongo.*
import org.slf4j.LoggerFactory
import java.util.concurrent.ConcurrentHashMap

object CustomDataService {
    private val logger = LoggerFactory.getLogger(CustomDataService::class.java)

    const val DEFAULT_ID = "default"

    val maxNumOfGallery = CUSTOM_CONFIG.maxSiteQtyOfWBGalleries

    @Volatile
    private lateinit var customData: CustomData

    // 物料暂存区任务触发数量，可通过PDA修改
    val wtTakeSize: MutableMap<String, Int> = ConcurrentHashMap()

    fun setWTTakeSize(galleryNameWithArea: String, newValue: Int, remoteAddr: String) {
        if (newValue !in 1..maxNumOfGallery)
            throw BusinessError("输入的值必须是大于0，小于${maxNumOfGallery + 1}的整数！")
        val oldValue = wtTakeSize[galleryNameWithArea]
        logger.debug("更新缓物料缓存区[$galleryNameWithArea]允许放置数量：from $oldValue to $newValue by $remoteAddr")
        if (oldValue == newValue) return
        wtTakeSize[galleryNameWithArea] = newValue
        setWTTakeSize(wtTakeSize)
    }

    // 人工PDA下单冻结库位
    fun setStoreSiteStatus(gallery: String, index: Int, disabled: Boolean, remoteAddr: String) {
        logger.debug("更新库位[$gallery$index]冻结状态：$disabled by $remoteAddr")
        val area = gallery.split("-")[0]
        if (area == "WT") {
            for (x in index..CUSTOM_CONFIG.rowZC) {
                StoreSiteService.changeSiteDisabled("$gallery-$x", disabled, "手动冻结库位以及之后库位")
            }
        } else {
            for (x in index..CUSTOM_CONFIG.rowRK) {
                StoreSiteService.changeSiteDisabled("$gallery-$x", disabled, "手动冻结库位以及之后库位")
            }
        }
    }

    fun setWTTakeSizeBatch(newValue: MutableMap<String, Int>, remark: String) {
        logger.debug("批量更新缓物料缓存区允许放置数量：from ${customData.wtTakeSize} to $newValue for $remark")
        newValue.forEach { (k, v) -> wtTakeSize[k] = v }
        setWTTakeSize(wtTakeSize)
    }

    // <toSiteId, confirmed>
    val agvStopAudio: MutableMap<String, Boolean> = ConcurrentHashMap()

    fun agvPlayAudio(toSiteId: String) {
        val old = agvStopAudio[toSiteId]
        if (old == false) return
        agvStopAudio[toSiteId] = false
        updateAgvStopAudio(agvStopAudio)
    }

    fun agvStopAudio(toSiteId: String) {
        val old = agvStopAudio[toSiteId]
        if (old != false) return
        agvStopAudio[toSiteId] = true
        updateAgvStopAudio(agvStopAudio)
    }

    fun removeRecordIfAgvStopAudio(toSiteId: String): Boolean {
        return when (agvStopAudio[toSiteId]) {
            false -> false
            null -> true
            true -> {
                agvStopAudio.remove(toSiteId)
                updateAgvStopAudio(agvStopAudio)
                true
            }
        }
    }

    fun stopCreateMatTransferTask(newValue: Boolean) {
        if (customData.stopCreateMatTransferTask != newValue) updateStopCreateMatTransferTask(newValue)
    }

    fun stopCreateMatInStoreTask(newValue: Boolean) {
        if (customData.stopCreateMatInStoreTask != newValue) updateStopCreateMatInStoreTask(newValue)
    }

    fun enableBoardCheck(newValue: Int) {
        if (customData.enableBoardCheck != newValue) updateEnableBoardCheck(newValue)
    }

    fun init() {
        customData = MongoDBManager.collection<CustomData>().findOne(CustomData::id eq DEFAULT_ID) ?: CustomData()
        setWTTakeSizeBatch(customData.wtTakeSize, "custom data init")
        customData.agvStopAudio.forEach { (key, value) -> agvStopAudio[key] = value }
    }

    fun getCustomData() = customData

    private fun updateAgvStopAudio(agvStopAudio: MutableMap<String, Boolean>) {
        customData = customData.copy(agvStopAudio = agvStopAudio)
        updateCustomData(customData)
    }

    private fun setWTTakeSize(wtTaskSize: MutableMap<String, Int>) {
        customData = customData.copy(wtTakeSize = wtTaskSize)
        updateCustomData(customData)
    }

    private fun updateStopCreateMatTransferTask(newValue: Boolean) {
        if (customData.stopCreateMatTransferTask == newValue) return
        customData = customData.copy(stopCreateMatTransferTask = newValue)
        updateCustomData(customData)
    }

    private fun updateStopCreateMatInStoreTask(newValue: Boolean) {
        if (customData.stopCreateMatInStoreTask == newValue) return
        customData = customData.copy(stopCreateMatInStoreTask = newValue)
        updateCustomData(customData)
    }

    private fun updateEnableBoardCheck(newValue: Int) {
        if (customData.enableBoardCheck == newValue) return
        customData = customData.copy(enableBoardCheck = newValue)
        updateCustomData(customData)
    }

    private fun updateCustomData(newCustomData: CustomData) {
        MongoDBManager.collection<CustomData>().updateOne(newCustomData, UpdateOptions().upsert(true))
    }

}

data class CustomData(
        @BsonId val id: String = CustomDataService.DEFAULT_ID,
        val agvStopAudio: MutableMap<String, Boolean> = mutableMapOf(),
        val stopCreateMatTransferTask: Boolean = false,
        val stopCreateMatInStoreTask: Boolean = false,
        val wtTakeSize: MutableMap<String, Int> = mutableMapOf(),
        val enableBoardCheck: Int = EnableBoardCheck.Enabled
)

object EnableBoardCheck {
    const val Enabled = 1
    const val Disabled = 0
    const val Unknown = -1

    fun toLabel(status: Int): String {
        return when (status) {
            Enabled -> "启用"
            Disabled -> "禁用"
            Unknown -> "未知"
            else -> throw BusinessError("Undefined status: $status")
        }
    }
}
